package com.doubao.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.doubao.common.result.Result;
import com.doubao.common.utils.RedisTemplateFactory;
import com.doubao.user.constant.UserConstant;
import com.doubao.user.dto.response.UserStatisticsResponse;
import com.doubao.user.entity.UserDailyToken;
import com.doubao.user.entity.UserStatistics;
import com.doubao.user.mapper.UserDailyTokenMapper;
import com.doubao.user.mapper.UserStatisticsMapper;
import com.doubao.user.service.UserStatisticsService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户统计服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserStatisticsServiceImpl extends ServiceImpl<UserStatisticsMapper, UserStatistics> implements UserStatisticsService {

    private final UserStatisticsMapper userStatisticsMapper;
    private final UserDailyTokenMapper userDailyTokenMapper;
    private RedisTemplate<String, Object> redisTemplate;
    
    @PostConstruct
    public void init() {
        this.redisTemplate = RedisTemplateFactory.getRedisTemplate();
        log.info("UserStatisticsServiceImpl使用RedisTemplateFactory获取RedisTemplate");
    }

    @Override
    public UserStatisticsResponse getUserStatistics(Long userId) {
        // 先从缓存获取
        UserStatisticsResponse cachedStats = (UserStatisticsResponse) redisTemplate.opsForValue().get(
                UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
        if (cachedStats != null) {
            return cachedStats;
        }

        // 获取基础统计数据
        UserStatistics baseStats = getBaseStatistics(userId);
        if (baseStats == null) {
            // 创建基础统计记录
            createUserStatistics(userId);
            baseStats = getBaseStatistics(userId);
            if (baseStats == null) {
                return new UserStatisticsResponse();
            }
        }

        // 构建响应对象
        UserStatisticsResponse response = new UserStatisticsResponse();
        BeanUtils.copyProperties(baseStats, response);

        // 获取今日token使用量
        int todayUsage = getTodayTokenUsage(userId);
        response.setTodayTokenUsage(todayUsage);

        // 计算今日token剩余量 - 在调用此方法前应该已经初始化了每日token记录
        LambdaQueryWrapper<UserDailyToken> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDailyToken::getUserId, userId)
                .eq(UserDailyToken::getDate, LocalDate.now());
        UserDailyToken dailyToken = userDailyTokenMapper.selectOne(wrapper);
        if (dailyToken != null) {
            response.setTodayTokenRemaining(Math.max(0, dailyToken.getLimitTokens() - todayUsage));
        }

        // 获取7天token使用趋势
        response.setTokenUsageTrend(getTokenUsageTrend(userId));

        // 计算使用时长（小时）
        if (baseStats.getLastActiveTime() != null && baseStats.getCreatedAt() != null) {
            Duration duration = Duration.between(baseStats.getCreatedAt(), baseStats.getLastActiveTime());
            response.setUsageHours((double) duration.toHours());
        }

        // 缓存结果
        redisTemplate.opsForValue().set(
                UserConstant.USER_STATISTICS_CACHE_PREFIX + userId,
                response,
                UserConstant.STATISTICS_CACHE_EXPIRE_SECONDS,
                TimeUnit.SECONDS);

        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> createUserStatistics(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        // 检查是否已存在
        LambdaQueryWrapper<UserStatistics> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserStatistics::getUserId, userId);
        if (userStatisticsMapper.selectCount(wrapper) > 0) {
            return Result.success(); // 已存在，直接返回成功
        }

        // 创建新记录
        UserStatistics statistics = new UserStatistics();
        statistics.setUserId(userId);
        statistics.setTotalChatCount(0);
        statistics.setTotalMessageCount(0);
        statistics.setTotalTokenUsage(0L);
        statistics.setDeviceCount(0);
        statistics.setCollectionCount(0);
        statistics.setLastActiveTime(LocalDateTime.now());
        statistics.setCreatedAt(LocalDateTime.now());
        statistics.setUpdatedAt(LocalDateTime.now());

        userStatisticsMapper.insert(statistics);
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> increaseChatCount(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.increaseChatCount(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("增加用户聊天次数失败", e);
            return Result.failed("增加聊天次数失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> increaseMessageCount(Long userId, Integer count) {
        if (userId == null || count == null || count <= 0) {
            return Result.failed("参数错误");
        }

        try {
            userStatisticsMapper.increaseMessageCount(userId, count);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("增加用户消息数失败", e);
            return Result.failed("增加消息数失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> increaseTokenUsage(Long userId, Integer promptTokens, Integer completionTokens) {
        if (userId == null || promptTokens == null || completionTokens == null) {
            return Result.failed("参数错误");
        }

        try {
            // 增加用户统计中的总token用量
            userStatisticsMapper.increaseTokenUsage(userId, (long)(promptTokens + completionTokens));

            // 记录每日token使用量
            LocalDate today = LocalDate.now();
            String dateStr = today.toString();

            // 先查询是否有当日记录
            LambdaQueryWrapper<UserDailyToken> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserDailyToken::getUserId, userId)
                    .eq(UserDailyToken::getDate, today);
            UserDailyToken dailyToken = userDailyTokenMapper.selectOne(wrapper);

            if (dailyToken == null) {
                // 创建新记录
                dailyToken = new UserDailyToken();
                dailyToken.setUserId(userId);
                dailyToken.setDate(today);
                dailyToken.setPromptTokens(promptTokens);
                dailyToken.setCompletionTokens(completionTokens);
                // 获取用户每日限额
                dailyToken.setLimitTokens(UserConstant.DEFAULT_DAILY_TOKENS_LIMIT); // 默认值
                // TODO: 从用户表获取实际限额
                dailyToken.setCreatedAt(LocalDateTime.now());
                dailyToken.setUpdatedAt(LocalDateTime.now());
                userDailyTokenMapper.insert(dailyToken);
            } else {
                // 更新现有记录
                userDailyTokenMapper.increasePromptTokens(userId, dateStr, promptTokens);
                userDailyTokenMapper.increaseCompletionTokens(userId, dateStr, completionTokens);
            }

            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("增加用户token使用量失败", e);
            return Result.failed("增加token使用量失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> increaseDeviceCount(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.increaseDeviceCount(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("增加用户智能体数量失败", e);
            return Result.failed("增加智能体数量失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> decreaseDeviceCount(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.decreaseDeviceCount(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("减少用户智能体数量失败", e);
            return Result.failed("减少智能体数量失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> increaseCollectionCount(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.increaseCollectionCount(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("增加用户收藏数量失败", e);
            return Result.failed("增加收藏数量失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> decreaseCollectionCount(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.decreaseCollectionCount(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("减少用户收藏数量失败", e);
            return Result.failed("减少收藏数量失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> updateLastActiveTime(Long userId) {
        if (userId == null) {
            return Result.failed("用户ID不能为空");
        }

        try {
            userStatisticsMapper.updateLastActiveTime(userId);
            // 清除缓存
            redisTemplate.delete(UserConstant.USER_STATISTICS_CACHE_PREFIX + userId);
            return Result.success();
        } catch (Exception e) {
            log.error("更新用户最后活跃时间失败", e);
            return Result.failed("更新最后活跃时间失败");
        }
    }

    @Override
    public UserStatistics getBaseStatistics(Long userId) {
        if (userId == null) {
            return null;
        }

        LambdaQueryWrapper<UserStatistics> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserStatistics::getUserId, userId);
        return userStatisticsMapper.selectOne(wrapper);
    }

    @Override
    public int getUserDailyTokenUsage(Long userId) {
        if (userId == null) {
            log.warn("获取用户每日token使用量时用户ID为空");
            return 0;
        }

        // 尝试从缓存获取今日token使用量
        String cacheKey = UserConstant.USER_DAILY_TOKEN_CACHE_PREFIX + userId + ":" + LocalDate.now();
        Integer cachedUsage = (Integer) redisTemplate.opsForValue().get(cacheKey);
        if (cachedUsage != null) {
            return cachedUsage;
        }

        // 缓存未命中，从数据库查询
        int todayUsage = getTodayTokenUsage(userId);

        // 将结果缓存，设置过期时间到今天结束
        LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59);
        long secondsUntilEndOfDay = Duration.between(LocalDateTime.now(), endOfDay).getSeconds();
        redisTemplate.opsForValue().set(cacheKey, todayUsage, secondsUntilEndOfDay, TimeUnit.SECONDS);

        return todayUsage;
    }

    @Override
    public int getTodayTokenUsage(Long userId) {
        if (userId == null) {
            return 0;
        }

        LocalDate today = LocalDate.now();
        LambdaQueryWrapper<UserDailyToken> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserDailyToken::getUserId, userId)
                .eq(UserDailyToken::getDate, today);
        UserDailyToken dailyToken = userDailyTokenMapper.selectOne(wrapper);

        if (dailyToken == null) {
            return 0;
        }

        return dailyToken.getPromptTokens() + dailyToken.getCompletionTokens();
    }

    @Override
    public Object getTokenUsageTrend(Long userId) {
        if (userId == null) {
            return new ArrayList<>();
        }

        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        List<Map<String, Object>> trendData = new ArrayList<>();

        // 查询最近7天数据
        for (int i = 6; i >= 0; i--) {
            LocalDate date = today.minusDays(i);
            String displayDate = date.format(formatter);

            LambdaQueryWrapper<UserDailyToken> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserDailyToken::getUserId, userId)
                    .eq(UserDailyToken::getDate, date);
            UserDailyToken dailyToken = userDailyTokenMapper.selectOne(wrapper);

            Map<String, Object> dayData = new HashMap<>();
            dayData.put("date", displayDate);
            dayData.put("promptTokens", dailyToken != null ? dailyToken.getPromptTokens() : 0);
            dayData.put("completionTokens", dailyToken != null ? dailyToken.getCompletionTokens() : 0);
            dayData.put("total", dailyToken != null ? (dailyToken.getPromptTokens() + dailyToken.getCompletionTokens()) : 0);

            trendData.add(dayData);
        }

        return trendData;
    }
}